import { BridgeConfig } from "./index";
import { BridgeChainProvider } from "./BridgeChainProvider";
import { Wallet } from "xrpl";
import { Log, LogStatus, LogType } from "../../util/Logger";
import { XChainBridge } from "xrpl/dist/npm/models/common";
import { XrpBridgeChainProvider } from "./XrpBridgeChainProvider";
import { EvmBridgeChainProvider } from "./EvmBridgeChainProvider";
import * as fs from "fs";
import { BridgeConfigType } from "../core/BridgeConfig";

export async function CreateBridge(config: BridgeConfig, exportConfigPath?: string) {
    const lockingService: BridgeChainProvider<Wallet | undefined> =
        config.lockingChain.type === "xrp" ? new XrpBridgeChainProvider() : new EvmBridgeChainProvider();
    const issuingService: BridgeChainProvider<Wallet | undefined> =
        config.issuingChain.type === "xrp" ? new XrpBridgeChainProvider() : new EvmBridgeChainProvider();

    const lockingWallet = lockingService.createBridgeWallet();
    const issuingWallet = issuingService.createBridgeWallet();

    let issuing: { address: string; tokenAddress?: string; config: XChainBridge },
        locking: { address: string; tokenAddress?: string; config: XChainBridge };

    if (lockingWallet) {
        issuing = await issuingService.createIssuingChainBridge(config, lockingWallet.address, issuingWallet);
        locking = await lockingService.createLockingChainBridge(config, issuing.address, lockingWallet);
    } else if (issuingWallet) {
        locking = await lockingService.createLockingChainBridge(config, issuingWallet.address, lockingWallet);
        issuing = await issuingService.createIssuingChainBridge(config, locking.address, issuingWallet);
    } else {
        throw new Error("There's no issuing or locking wallet set, currently creating a bridge EVM to EVM is not supported");
    }

    Log(
        LogType.Bridge,
        LogStatus.Done,
        `Bridge created successfully
        Locking config
        ${JSON.stringify(locking, undefined, 4)}
        Issuing config: ${JSON.stringify(issuing, undefined, 4)}`,
    );

    if (exportConfigPath) {
        const exportConfig: BridgeConfigType = {
            lockingChain: {
                type: config.lockingChain.type,
                nodeUrl: config.lockingChain.url,
                bridgeAccount: locking.address,
                feePrivateKey: config.lockingChain.fundingPrivateKey,
                currency: {
                    issuer: config.lockingChain.tokenIssuer,
                    currency: config.lockingChain.tokenCode,
                },
                XChainBridge: locking.config,
                tokenAddress: config.lockingChain.tokenAddress || locking.tokenAddress || "",
            },
            issuingChain: {
                type: config.issuingChain.type,
                nodeUrl: config.issuingChain.url,
                bridgeAccount: issuing.address,
                feePrivateKey: config.issuingChain.fundingPrivateKey,
                currency: {
                    issuer: issuing.address,
                    currency: config.lockingChain.tokenCode,
                },
                XChainBridge: issuing.config,
                tokenAddress: config.issuingChain.tokenAddress || issuing.tokenAddress || "",
            },
            params: {
                minCreateAmount: config.minCreateAmount,
                signatureReward: config.minRewardAmount,
                threshold: config.threshold,
            },
        };
        fs.writeFileSync(exportConfigPath, JSON.stringify(exportConfig, undefined, 4));
        Log(LogType.Bridge, LogStatus.Done, `Exported bridge config to ${exportConfigPath}`);
    }
}
